Reactμ experimental_useSyncExternalStore ν μ μ¬μ©νμ¬ μΈλΆ μ μ₯μλ₯Ό λκΈ°ννκ³ , μ μΈκ³ κ°λ°μλ₯Ό μν ꡬν, μ¬μ© μ¬λ‘, λͺ¨λ² μ¬λ‘μ μ€μ μ λ‘λλ€.
Reactμ experimental_useSyncExternalStore λ§μ€ν°νκΈ°: ν¬κ΄μ μΈ κ°μ΄λ
Reactμ experimental_useSyncExternalStore ν
μ React μ»΄ν¬λνΈλ₯Ό μΈλΆ λ°μ΄ν° μμ€μ λκΈ°ννκΈ° μν κ°λ ₯ν λꡬμ
λλ€. μ΄ ν
μ μ¬μ©νλ©΄ μ»΄ν¬λνΈκ° μΈλΆ μ μ₯μμ λ³κ²½ μ¬νμ ν¨μ¨μ μΌλ‘ ꡬλ
νκ³ νμν κ²½μ°μλ§ λ€μ λ λλ§ν μ μμ΅λλ€. experimental_useSyncExternalStoreμ ν¨κ³Όμ μΌλ‘ μ΄ν΄νκ³ κ΅¬ννλ κ²μ λ€μν μΈλΆ λ°μ΄ν° κ΄λ¦¬ μμ€ν
κ³Ό μννκ² ν΅ν©λλ κ³ μ±λ₯ React μ ν리μΌμ΄μ
μ ꡬμΆνλ λ° λ§€μ° μ€μν©λλ€.
μΈλΆ μ μ₯μλ 무μμΈκ°μ?
ν μ ꡬ체μ μΈ λ΄μ©μ μ΄ν΄λ³΄κΈ° μ μ "μΈλΆ μ μ₯μ"κ° λ¬΄μμ μλ―Ένλμ§ μ μνλ κ²μ΄ μ€μν©λλ€. μΈλΆ μ μ₯μλ Reactμ λ΄λΆ μν μΈλΆμ μ‘΄μ¬νλ λͺ¨λ λ°μ΄ν° 컨ν μ΄λ λλ μν κ΄λ¦¬ μμ€ν μ λλ€. μ¬κΈ°μλ λ€μμ΄ ν¬ν¨λ μ μμ΅λλ€.
- κΈλ‘λ² μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬: Redux, Zustand, Jotai, Recoil
- λΈλΌμ°μ API:
localStorage,sessionStorage,IndexedDB - λ°μ΄ν° κ°μ Έμ€κΈ° λΌμ΄λΈλ¬λ¦¬: SWR, React Query
- μ€μκ° λ°μ΄ν° μμ€: WebSockets, Server-Sent Events
- νμ¬ λΌμ΄λΈλ¬λ¦¬: React μ»΄ν¬λνΈ νΈλ¦¬ μΈλΆμμ κ΅¬μ± λλ λ°μ΄ν°λ₯Ό κ΄λ¦¬νλ λΌμ΄λΈλ¬λ¦¬.
μ΄λ¬ν μΈλΆ λ°μ΄ν° μμ€μ ν¨κ³Όμ μΌλ‘ ν΅ν©νλ κ²μ μ’
μ’
μ΄λ €μμ μΌκΈ°ν©λλ€. Reactμ λ΄μ₯ μν κ΄λ¦¬κ° μΆ©λΆνμ§ μμ μ μμΌλ©°, μ΄λ¬ν μΈλΆ μμ€μ λ³κ²½ μ¬νμ μλμΌλ‘ ꡬλ
νλ©΄ μ±λ₯ λ¬Έμ κ° λ°μνκ³ μ½λκ° λ³΅μ‘ν΄μ§ μ μμ΅λλ€. experimental_useSyncExternalStoreμ React μ»΄ν¬λνΈλ₯Ό μΈλΆ μ μ₯μμ λκΈ°ννλ νμ€νλκ³ μ΅μ νλ λ°©λ²μ μ 곡νμ¬ μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°ν©λλ€.
experimental_useSyncExternalStore μκ°
experimental_useSyncExternalStore ν
μ Reactμ μ€νμ κΈ°λ₯μ μΌλΆμ΄λ―λ‘ APIκ° ν₯ν 릴리μ€μμ λ³κ²½λ μ μμ΅λλ€. κ·Έλ¬λ ν΅μ¬ κΈ°λ₯μ λ§μ React μ ν리μΌμ΄μ
μμ κΈ°λ³Έμ μΈ μꡬ μ¬νμ ν΄κ²°νλ―λ‘ μ΄ν΄νκ³ μ€νν΄ λ³Ό κ°μΉκ° μμ΅λλ€.
ν μ κΈ°λ³Έ μκ·Έλμ²λ λ€μκ³Ό κ°μ΅λλ€.
const value = experimental_useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?);
κ° μΈμλ₯Ό μμΈν μ΄ν΄λ³΄κ² μ΅λλ€.
subscribe: (callback: () => void) => () => void: μ΄ ν¨μλ μΈλΆ μ μ₯μμ λ³κ²½ μ¬νμ ꡬλ νλ μν μ ν©λλ€. μ½λ°± ν¨μλ₯Ό μΈμλ‘ μ¬μ©νλ©°, Reactλ μ μ₯μκ° λ³κ²½λ λλ§λ€ μ΄ μ½λ°± ν¨μλ₯Ό νΈμΆν©λλ€.subscribeν¨μλ νΈμΆ μ μ½λ°±μ μ μ₯μμμ ꡬλ ν΄μ νλ λ€λ₯Έ ν¨μλ₯Ό λ°νν΄μΌ ν©λλ€. μ΄λ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§νλ λ° λ§€μ° μ€μν©λλ€.getSnapshot: () => T: μ΄ ν¨μλ μΈλΆ μ μ₯μμμ λ°μ΄ν°μ μ€λ μ·μ λ°νν©λλ€. Reactλ μ΄ μ€λ μ·μ μ¬μ©νμ¬ λ§μ§λ§ λ λλ§ μ΄ν λ°μ΄ν°κ° λ³κ²½λμλμ§ μ¬λΆλ₯Ό κ²°μ ν©λλ€. μμ ν¨μ(λΆμμ© μμ)μ¬μΌ ν©λλ€.getServerSnapshot?: () => T(μ ν μ¬ν): μ΄ ν¨μλ μλ² μΈ‘ λ λλ§(SSR) μ€μλ§ μ¬μ©λ©λλ€. μλ² λ λλ§λ HTMLμ λν λ°μ΄ν°μ μ΄κΈ° μ€λ μ·μ μ 곡ν©λλ€. μ 곡νμ§ μμΌλ©΄ Reactλ SSR μ€μ μ€λ₯λ₯Ό λ°μμν΅λλ€. μ΄ ν¨μλ μμν΄μΌ ν©λλ€.
μ΄ ν μ μΈλΆ μ μ₯μμμ λ°μ΄ν°μ νμ¬ μ€λ μ·μ λ°νν©λλ€. μ΄ κ°μ μ»΄ν¬λνΈκ° λ λλ§λ λλ§λ€ μΈλΆ μ μ₯μμ μ΅μ μνλ‘ μ μ§λ©λλ€.
experimental_useSyncExternalStore μ¬μ©μ μ΄μ
experimental_useSyncExternalStoreμ μ¬μ©νλ©΄ μΈλΆ μ μ₯μμ λν ꡬλ
μ μλμΌλ‘ κ΄λ¦¬νλ κ²λ³΄λ€ λͺ κ°μ§ μ΄μ μ΄ μμ΅λλ€.
- μ±λ₯ μ΅μ ν: Reactλ μ€λ μ·μ λΉκ΅νμ¬ λ°μ΄ν°κ° λ³κ²½λμλμ§ ν¨μ¨μ μΌλ‘ νλ¨ν μ μμΌλ―λ‘ λΆνμν μ¬λ λλ§μ λ°©μ§ν μ μμ΅λλ€.
- μλ μ λ°μ΄νΈ: Reactλ μΈλΆ μ μ₯μλ₯Ό μλμΌλ‘ ꡬλ λ° κ΅¬λ ν΄μ νμ¬ μ»΄ν¬λνΈ λ‘μ§μ λ¨μννκ³ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§ν©λλ€.
- SSR μ§μ:
getServerSnapshotν¨μλ μΈλΆ μ μ₯μλ₯Ό μ¬μ©νμ¬ μνν μλ² μΈ‘ λ λλ§μ κ°λ₯νκ² ν©λλ€. - λμμ± μμ μ±: μ΄ ν μ Reactμ λμ λ λλ§ κΈ°λ₯κ³Ό μ¬λ°λ₯΄κ² μλνλλ‘ μ€κ³λμ΄ λ°μ΄ν°κ° νμ μΌκ΄μ±μ μ μ§νλλ‘ ν©λλ€.
- λ¨μνλ μ½λ: μλ ꡬλ λ° μ λ°μ΄νΈμ κ΄λ ¨λ μμ©κ΅¬ μ½λλ₯Ό μ€μ λλ€.
μ€μ©μ μΈ μμ λ° μ¬μ© μ¬λ‘
experimental_useSyncExternalStoreμ κ°λ ₯ν¨μ μ€λͺ
νκΈ° μν΄ λͺ κ°μ§ μ€μ©μ μΈ μλ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€.
1. κ°λ¨ν μ¬μ©μ μ§μ μ μ₯μμ ν΅ν©
λ¨Όμ , μΉ΄μ΄ν°λ₯Ό κ΄λ¦¬νλ κ°λ¨ν μ¬μ©μ μ§μ μ μ₯μλ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€.
// counterStore.js
let count = 0;
let listeners = [];
const counterStore = {
subscribe: (listener) => {
listeners = [...listeners, listener];
return () => {
listeners = listeners.filter((l) => l !== listener);
};
},
getSnapshot: () => count,
increment: () => {
count++;
listeners.forEach((listener) => listener());
},
};
export default counterStore;
μ΄μ experimental_useSyncExternalStoreμ μ¬μ©νμ¬ μΉ΄μ΄ν°λ₯Ό νμνκ³ μ
λ°μ΄νΈνλ React μ»΄ν¬λνΈλ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€.
// CounterComponent.jsx
import React from 'react';
import { experimental_useSyncExternalStore } from 'react';
import counterStore from './counterStore';
function CounterComponent() {
const count = experimental_useSyncExternalStore(
counterStore.subscribe,
counterStore.getSnapshot
);
return (
<div>
<p>Count: {count}</p>
<button onClick={counterStore.increment}>Increment</button>
</div>
);
}
export default CounterComponent;
μ΄ μμμ CounterComponentλ experimental_useSyncExternalStoreμ μ¬μ©νμ¬ counterStoreμ λ³κ²½ μ¬νμ ꡬλ
ν©λλ€. increment ν¨μκ° μ μ₯μμμ νΈμΆλ λλ§λ€ μ»΄ν¬λνΈκ° λ€μ λ λλ§λμ΄ μ
λ°μ΄νΈλ μΉ΄μ΄νΈκ° νμλ©λλ€.
2. localStorageμ ν΅ν©
localStorageλ λΈλΌμ°μ μμ λ°μ΄ν°λ₯Ό μ μ§νλ μΌλ°μ μΈ λ°©λ²μ
λλ€. experimental_useSyncExternalStoreκ³Ό ν΅ν©νλ λ°©λ²μ μ΄ν΄λ³΄κ² μ΅λλ€.
// localStorageStore.js
const localStorageStore = {
subscribe: (listener) => {
window.addEventListener('storage', listener);
return () => {
window.removeEventListener('storage', listener);
};
},
getSnapshot: (key) => {
try {
return localStorage.getItem(key) || '';
} catch (error) {
console.error("Error accessing localStorage:", error);
return '';
}
},
setItem: (key, value) => {
try {
localStorage.setItem(key, value);
window.dispatchEvent(new Event('storage')); // Manually trigger storage event
} catch (error) {
console.error("Error setting localStorage:", error);
}
},
};
export default localStorageStore;
`localStorage`μ λν μ€μ μ¬ν:
- `storage` μ΄λ²€νΈλ λμΌν μΆμ²μ μ‘μΈμ€νλ *λ€λ₯Έ* λΈλΌμ°μ 컨ν μ€νΈ(μ: λ€λ₯Έ ν, μ°½)μμλ§ λ°μν©λλ€. λμΌν ν λ΄μμλ νλͺ©μ μ€μ ν ν μ΄λ²€νΈλ₯Ό μλμΌλ‘ λμ€ν¨μΉν΄μΌ ν©λλ€.
- `localStorage`λ μ€λ₯λ₯Ό λ°μμν¬ μ μμ΅λλ€(μ: ν λΉλμ΄ μ΄κ³Όλ κ²½μ°). `try...catch` λΈλ‘μΌλ‘ μμ μ λννλ κ²μ΄ μ€μν©λλ€.
μ΄μ μ΄ μ μ₯μλ₯Ό μ¬μ©νλ React μ»΄ν¬λνΈλ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€.
// LocalStorageComponent.jsx
import React, { useState } from 'react';
import { experimental_useSyncExternalStore } from 'react';
import localStorageStore from './localStorageStore';
function LocalStorageComponent({ key }) {
const [inputValue, setInputValue] = useState('');
const storedValue = experimental_useSyncExternalStore(
localStorageStore.subscribe,
() => localStorageStore.getSnapshot(key)
);
const handleChange = (event) => {
setInputValue(event.target.value);
};
const handleSave = () => {
localStorageStore.setItem(key, inputValue);
};
return (
<div>
<label>Value for key "{key}":</label>
<input type="text" value={inputValue} onChange={handleChange} />
<button onClick={handleSave}>Save to LocalStorage</button>
<p>Stored Value: {storedValue}</p>
</div>
);
}
export default LocalStorageComponent;
μ΄ μ»΄ν¬λνΈλ₯Ό ν΅ν΄ μ¬μ©μλ ν
μ€νΈλ₯Ό μ
λ ₯νκ³ localStorageμ μ μ₯νλ©° μ μ₯λ κ°μ νμν μ μμ΅λλ€. experimental_useSyncExternalStore ν
μ λ€λ₯Έ ν λλ μ°½μμ μ
λ°μ΄νΈλ κ²½μ°μλ μ»΄ν¬λνΈκ° νμ localStorageμ μ΅μ κ°μ λ°μνλλ‘ ν©λλ€.
3. κΈλ‘λ² μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬(Zustand)μ ν΅ν©
λ 볡μ‘ν μ ν리μΌμ΄μ
μ κ²½μ° Zustandμ κ°μ κΈλ‘λ² μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν μ μμ΅λλ€. experimental_useSyncExternalStoreκ³Ό Zustandλ₯Ό ν΅ν©νλ λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
// zustandStore.js
import { create } from 'zustand';
const useZustandStore = create((set) => ({
items: [],
addItem: (item) => set((state) => ({ items: [...state.items, item] })),
removeItem: (itemId) =>
set((state) => ({ items: state.items.filter((item) => item.id !== itemId) })),
}));
export default useZustandStore;
μ΄μ React μ»΄ν¬λνΈλ₯Ό λ§λλλ€.
// ZustandComponent.jsx
import React, { useState } from 'react';
import { experimental_useSyncExternalStore } from 'react';
import useZustandStore from './zustandStore';
import { v4 as uuidv4 } from 'uuid';
function ZustandComponent() {
const [itemName, setItemName] = useState('');
const items = experimental_useSyncExternalStore(
useZustandStore.subscribe,
useZustandStore.getState
).items;
const handleAddItem = () => {
if (itemName.trim() !== '') {
useZustandStore.getState().addItem({ id: uuidv4(), name: itemName });
setItemName('');
}
};
const handleRemoveItem = (itemId) => {
useZustandStore.getState().removeItem(itemId);
};
return (
<div>
<input
type="text"
value={itemName}
onChange={(e) => setItemName(e.target.value)}
placeholder="Item Name"
/>
<button onClick={handleAddItem}>Add Item</button>
<ul>
{items.map((item) => (
<li key={item.id}>
{item.name}
<button onClick={() => handleRemoveItem(item.id)}>Remove</button>
</li>
))}
</ul>
</div>
);
}
export default ZustandComponent;
μ΄ μμμ ZustandComponentλ Zustand μ μ₯μλ₯Ό ꡬλ
νκ³ νλͺ© λͺ©λ‘μ νμν©λλ€. νλͺ©μ΄ μΆκ°λκ±°λ μ κ±°λλ©΄ μ»΄ν¬λνΈκ° μλμΌλ‘ λ€μ λ λλ§λμ΄ Zustand μ μ₯μμ λ³κ²½ μ¬νμ λ°μν©λλ€.
experimental_useSyncExternalStoreμ μ¬μ©ν μλ² μΈ‘ λ λλ§(SSR)
μλ² μΈ‘ λ λλ§λ μ ν리μΌμ΄μ
μμ experimental_useSyncExternalStoreμ μ¬μ©νλ κ²½μ° getServerSnapshot ν¨μλ₯Ό μ 곡ν΄μΌ ν©λλ€. μ΄ ν¨μλ₯Ό μ¬μ©νλ©΄ Reactκ° μλ² μΈ‘ λ λλ§ μ€μ λ°μ΄ν°μ μ΄κΈ° μ€λ
μ·μ μ»μ μ μμ΅λλ€. κ·Έλ μ§ μμΌλ©΄ Reactλ μλ²μμ μΈλΆ μ μ₯μμ μ‘μΈμ€ν μ μμΌλ―λ‘ μ€λ₯λ₯Ό λ°μμν΅λλ€.
SSRμ μ§μνλλ‘ κ°λ¨ν μΉ΄μ΄ν° μμ λ₯Ό μμ νλ λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
// counterStore.js (SSR-enabled)
let count = 0;
let listeners = [];
const counterStore = {
subscribe: (listener) => {
listeners = [...listeners, listener];
return () => {
listeners = listeners.filter((l) => l !== listener);
};
},
getSnapshot: () => count,
getServerSnapshot: () => 0, // Provide an initial value for SSR
increment: () => {
count++;
listeners.forEach((listener) => listener());
},
};
export default counterStore;
μ΄ μμ λ λ²μ μμλ μΉ΄μ΄ν°μ λν μ΄κΈ° κ° 0μ λ°ννλ getServerSnapshot ν¨μλ₯Ό μΆκ°νμ΅λλ€. μ΄λ κ² νλ©΄ μλ² λ λλ§λ HTMLμ μΉ΄μ΄ν°μ λν μ ν¨ν κ°μ΄ ν¬ν¨λκ³ ν΄λΌμ΄μΈνΈ μΈ‘ μ»΄ν¬λνΈκ° μλ² λ λλ§λ HTMLμμ μννκ² νμ΄λλ μ΄μ
λ μ μμ΅λλ€.
λ°μ΄ν°λ² μ΄μ€μμ κ°μ Έμ¨ λ°μ΄ν°λ₯Ό μ²λ¦¬νλ κ²½μ°μ κ°μ΄ λ 볡μ‘ν μλ리μ€μμλ μλ²μμ λ°μ΄ν°λ₯Ό κ°μ Έμ getServerSnapshotμμ μ΄κΈ° μ€λ
μ·μΌλ‘ μ 곡ν΄μΌ ν©λλ€.
λͺ¨λ² μ¬λ‘ λ° κ³ λ € μ¬ν
experimental_useSyncExternalStoreμ μ¬μ©ν λλ λ€μ λͺ¨λ² μ¬λ‘λ₯Ό μΌλμ λμμμ€.
getSnapshotμ μμνκ² μ μ§:getSnapshotν¨μλ λΆμμ©μ΄ μμμ μλ―Ένλ μμ ν¨μμ¬μΌ ν©λλ€. μΈλΆ μ μ₯μλ₯Ό μμ νμ§ μκ³ λ°μ΄ν°μ μ€λ μ·λ§ λ°νν΄μΌ ν©λλ€.- μ€λ
μ· ν¬κΈ° μ΅μν:
getSnapshotμμ λ°ννλ μ€λ μ·μ ν¬κΈ°λ₯Ό μ΅μννμμμ€. Reactλ μ€λ μ·μ λΉκ΅νμ¬ λ°μ΄ν°κ° λ³κ²½λμλμ§ μ¬λΆλ₯Ό κ²°μ νλ―λ‘ μ€λ μ·μ΄ μμμλ‘ μ±λ₯μ΄ ν₯μλ©λλ€. - ꡬλ
λ‘μ§ μ΅μ ν:
subscribeν¨μκ° μΈλΆ μ μ₯μμ λ³κ²½ μ¬νμ ν¨μ¨μ μΌλ‘ ꡬλ νλλ‘ ν©λλ€. μ ν리μΌμ΄μ μλλ₯Ό λ¦μΆ μ μλ λΆνμν ꡬλ μ΄λ 볡μ‘ν λ‘μ§μ νΌνμμμ€. - μ€λ₯λ₯Ό μ μμ μΌλ‘ μ²λ¦¬:
localStorageμ κ°μ΄ μ μ₯μ ν λΉλμ΄ μ΄κ³Όλ μ μλ νκ²½μμ νΉν μΈλΆ μ μ₯μμ μ‘μΈμ€ν λ λ°μν μ μλ μ€λ₯λ₯Ό μ²λ¦¬ν μ€λΉλ₯Ό νμμμ€. - λ©λͺ¨μ΄μ μ΄μ
κ³ λ €: μ€λ
μ·μ μμ±νλ λ° κ³μ° λΉμ©μ΄ λ§μ΄ λλ κ²½μ°
getSnapshotμ κ²°κ³Όλ₯Ό λ©λͺ¨μ΄μ μ΄μ νμ¬ μ€λ³΅ κ³μ°μ λ°©μ§νλ κ²μ κ³ λ €νμμμ€.useMemoμ κ°μ λΌμ΄λΈλ¬λ¦¬κ° λμμ΄ λ μ μμ΅λλ€. - λμ λͺ¨λμ μ μ: μΈλΆ μ μ₯μκ° Reactμ λμ λ λλ§ κΈ°λ₯κ³Ό νΈνλλμ§ νμΈνμμμ€. λμ λͺ¨λλ λ λλ§μ 컀λ°νκΈ° μ μ
getSnapshotμ μ¬λ¬ λ² νΈμΆν μ μμ΅λλ€.
κΈλ‘λ² κ³ λ € μ¬ν
κΈλ‘λ² μ¬μ©μλ₯Ό μν΄ React μ ν리μΌμ΄μ μ κ°λ°ν λλ μΈλΆ μ μ₯μμ ν΅ν©ν λ λ€μ μΈ‘λ©΄μ κ³ λ €νμμμ€.
- μκ°λ: μΈλΆ μ μ₯μμμ λ μ§ λλ μκ°μ κ΄λ¦¬νλ κ²½μ° λ€λ₯Έ μ§μμ μ¬μ©μμκ² λΆμΌμΉκ° λ°μνμ§ μλλ‘ μκ°λλ₯Ό μ¬λ°λ₯΄κ² μ²λ¦¬νμμμ€.
date-fns-tzλλmoment-timezoneκ³Ό κ°μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μκ°λλ₯Ό κ΄λ¦¬νμμμ€. - νμ§ν: μΈλΆ μ μ₯μμ νμ§νκ° νμν ν
μ€νΈ λλ κΈ°ν μ½ν
μΈ κ° ν¬ν¨λ κ²½μ°
i18nextλλreact-intlκ³Ό κ°μ νμ§ν λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ¬μ©μμ μΈμ΄ κΈ°λ³Έ μ€μ μ λ°λΌ νμ§νλ μ½ν μΈ λ₯Ό μ 곡νμμμ€. - ν΅ν: μΈλΆ μ μ₯μμμ κΈμ΅ λ°μ΄ν°λ₯Ό κ΄λ¦¬νλ κ²½μ° ν΅νλ₯Ό μ¬λ°λ₯΄κ² μ²λ¦¬νκ³ λ€μν λ‘μΌμΌμ μ ν©ν νμμ μ 곡νμμμ€.
currency.jsλλaccounting.jsμ κ°μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ ν΅νλ₯Ό κ΄λ¦¬νμμμ€. - λ°μ΄ν° κ°μΈ μ 보 보νΈ:
localStorageλλsessionStorageμ κ°μ μΈλΆ μ μ₯μμ μ¬μ©μ λ°μ΄ν°λ₯Ό μ μ₯ν λ GDPRκ³Ό κ°μ λ°μ΄ν° κ°μΈ μ 보 λ³΄νΈ κ·μ μ μΌλμ λμμμ€. λ―Όκ°ν λ°μ΄ν°λ₯Ό μ μ₯νκΈ° μ μ μ¬μ©μ λμλ₯Ό μ»κ³ μ¬μ©μκ° λ°μ΄ν°λ₯Ό μ‘μΈμ€νκ³ μμ ν μ μλ λ©μ»€λμ¦μ μ 곡νμμμ€.
experimental_useSyncExternalStoreμ λμ
experimental_useSyncExternalStoreλ κ°λ ₯ν λꡬμ΄μ§λ§ React μ»΄ν¬λνΈλ₯Ό μΈλΆ μ μ₯μμ λκΈ°ννλ λ체 λ°©λ²μ΄ μμ΅λλ€.
- Context API: Reactμ Context APIλ₯Ό μ¬μ©νμ¬ μΈλΆ μ μ₯μμμ μ»΄ν¬λνΈ νΈλ¦¬λ‘ λ°μ΄ν°λ₯Ό μ 곡ν μ μμ΅λλ€. κ·Έλ¬λ Context APIλ μ
λ°μ΄νΈκ° λΉλ²ν λκ·λͺ¨ μ ν리μΌμ΄μ
μ κ²½μ°
experimental_useSyncExternalStoreλ§νΌ ν¨μ¨μ μ΄μ§ μμ μ μμ΅λλ€. - Render Props: Render propsλ₯Ό μ¬μ©νμ¬ μΈλΆ μ μ₯μμ λ³κ²½ μ¬νμ ꡬλ νκ³ λ°μ΄ν°λ₯Ό μμ μ»΄ν¬λνΈμ μ λ¬ν μ μμ΅λλ€. κ·Έλ¬λ λ λ propλ 볡μ‘ν μ»΄ν¬λνΈ κ³μΈ΅ ꡬ쑰μ μ μ§ κ΄λ¦¬κ° μ΄λ €μ΄ μ½λλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
- μ¬μ©μ μ§μ ν : μ¬μ©μ μ§μ ν μ μμ±νμ¬ μΈλΆ μ μ₯μμ λν ꡬλ μ κ΄λ¦¬ν μ μμ΅λλ€. κ·Έλ¬λ μ΄ μ κ·Ό λ°©μμ μ±λ₯ μ΅μ ν λ° μ€λ₯ μ²λ¦¬μ μ£Όμλ₯Ό κΈ°μΈμ¬μΌ ν©λλ€.
μ΄λ€ μ κ·Ό λ°©μμ μ¬μ©ν μ§λ μ ν리μΌμ΄μ
μ νΉμ μꡬ μ¬νμ λ°λΌ λ€λ¦
λλ€. experimental_useSyncExternalStoreλ μ
λ°μ΄νΈκ° λΉλ²νκ³ κ³ μ±λ₯μ΄ νμν 볡μ‘ν μ ν리μΌμ΄μ
μ κ°μ₯ μ ν©ν κ²½μ°κ° λ§μ΅λλ€.
κ²°λ‘
experimental_useSyncExternalStoreμ React μ»΄ν¬λνΈλ₯Ό μΈλΆ λ°μ΄ν° μμ€μ λκΈ°ννλ κ°λ ₯νκ³ ν¨μ¨μ μΈ λ°©λ²μ μ 곡ν©λλ€. ν΅μ¬ κ°λ
, μ€μ©μ μΈ μμ λ° λͺ¨λ² μ¬λ‘λ₯Ό μ΄ν΄ν¨μΌλ‘μ¨ κ°λ°μλ λ€μν μΈλΆ λ°μ΄ν° κ΄λ¦¬ μμ€ν
κ³Ό μννκ² ν΅ν©λλ κ³ μ±λ₯ React μ ν리μΌμ΄μ
μ ꡬμΆν μ μμ΅λλ€. Reactκ° κ³μ λ°μ ν¨μ λ°λΌ experimental_useSyncExternalStoreλ μ μΈκ³ μ¬μ©μλ₯Ό μν 볡μ‘νκ³ νμ₯ κ°λ₯ν μ ν리μΌμ΄μ
μ ꡬμΆνλ λ° λμ± μ€μν λκ΅¬κ° λ κ²μ
λλ€. νλ‘μ νΈμ ν΅ν©ν λ μ€νμ μνμ μ μ¬μ μΈ API λ³κ²½ μ¬νμ μ μ€νκ² κ³ λ €νμμμ€. μ΅μ μ
λ°μ΄νΈ λ° κΆμ₯ μ¬νμ νμ 곡μ React μ€λͺ
μλ₯Ό μ°Έμ‘°νμμμ€.